Import data
observations
filenames <- list.files(here("source"),pattern="*.gpkg$")
layers_s = c("09h30_staying","12h30_staying","15h30_staying","18h30_staying")
layers_m = c("09h30_moving","12h30_moving","15h30_moving","18h30_moving")
list_m = list()
list_s = list()
for (i in filenames) {
filename = i
for (j in layers_s) {
df = st_read(here("source",filename),j)
df$fileid = filename
df$layer = j
df = df %>% dplyr::select(-Photo,-mode,-row,-id)
list_s[[length(list_s)+1]]=df
rm(df)
}
for (j in layers_m) {
df = st_read(here("source",filename),j)
df$fileid = paste0(filename,j)
df$fileid = filename
df$layer = j
df = df %>% dplyr::select(-Direction,-Photo)
list_m[[length(list_m)+1]]=df
rm(df)
}
rm(filename)
}
df_s = rbindlist(list_s,use.names = FALSE) %>% st_as_sf()
df_s %>% ggplot() + geom_sf()
df_m = rbindlist(list_m,use.names = FALSE) %>% st_as_sf()
df_m %>% ggplot() + geom_sf()
context
buildings <- read_sf(here("source","geom","context.gpkg"),"buildings")
plot(buildings)
boundary = read_sf(here("source","geom","context.gpkg"),"perimetre") %>% slice(1)
plot(boundary)
zones = read_sf(here("source","geom","context.gpkg"),"zones")
plot(zones)
track = read_sf(here("source","geom","track.gpkg"),"track3")
plot(track)
basemap = stack(here("source","geom","basemap.tif"))
basemap_df = as.data.frame(basemap, xy= TRUE)
basemap_df =
basemap_df %>%
rename(red = basemap_1, #Rename bands
green = basemap_2,
blue = basemap_3) %>%
filter(red != 0) #drop data w/o rgb information
map = stack(here("source","geom","map_georeferenced_clip.tif"))
map_df = as.data.frame(map, xy= TRUE)
map_df =
map_df %>%
rename(red = map_georeferenced_clip_1, #Rename bands
green = map_georeferenced_clip_2,
blue = map_georeferenced_clip_3) %>%
filter(red != 0) #drop data w/o rgb information
bbox <- st_bbox(st_buffer(boundary,dist = 5, joinStyle="ROUND")) #global
#Data organisation
IDs
#survey_id
df_s$survey_id <- paste0(substr(df_s$path,start=76,stop=81),"_",substr(df_s$path,start=83,stop=87))
df_s$survey_id<-gsub("-","",df_s$survey_id)
df_s$survey_id<-gsub("_","",df_s$survey_id)
df_m$survey_id <- paste0(substr(df_m$path,start=76,stop=81),"_",substr(df_m$path,start=83,stop=87))
df_m$survey_id<-gsub("-","",df_m$survey_id)
df_m$survey_id<-gsub("_","",df_m$survey_id)
# row_id
df_s$row_id <- paste(df_s$survey_id, ave(df_s$id,df_s$survey_id, FUN = seq_along), sep="")
Error in split.default(x, g) : first argument must be a vector
Means & totals
# Row_total
df_s$row_total <- df_s$gender_male+df_s$gender_female
df_m$row_total <- df_m$gender_male+df_m$gender_female
# Mean age per group
df_s$age_mean <- round(((df_s$age_0.14*7)+(df_s$age_15.24*19.5)+(df_s$age_25.44*34.5)+
(df_s$age_45.64*54.5)+(df_s$age_65.74*69.5)+
(df_s$age_75p*80))/df_s$row_total,digits = 1)
df_m$age_mean <- round(((df_m$age_0.14*7)+(df_m$age_15.24*19.5)+(df_m$age_25.44*34.5)+
(df_m$age_45.64*54.5)+(df_m$age_65.74*69.5)+
(df_m$age_75p*80))/df_m$row_total,digits = 1)
Separating columns of time & date from timestamp
df_s$timestamp <- gsub('T',' ',df_s$timestamp)
df_s$timestamp <- substr(df_s$timestamp,start=1,stop=19)
df_s$date <- format(as.POSIXct(strptime(df_s$timestamp,"%Y-%m-%d",tz="")),format = "%Y-%m-%d") # separate date column
df_s$time <- format(as.POSIXct(strptime(df_s$timestamp,"%Y-%m-%d %H:%M:%S",tz="")) ,format = "%H:%M:%S") # separate time column
df_m$timestamp <- gsub('T',' ',df_m$timestamp)
df_m$timestamp <- substr(df_m$timestamp,start=1,stop=19)
df_m$date <- format(as.POSIXct(strptime(df_m$timestamp,"%Y-%m-%d",tz="")),format = "%Y-%m-%d") # separate date column
df_m$time <- format(as.POSIXct(strptime(df_m$timestamp,"%Y-%m-%d %H:%M:%S",tz="")) ,format = "%H:%M:%S") # separate time column
Adding coordinates WGS84
library(sf)
#conversion of points into spatial feature object
df_s_lb93 <- st_as_sf(df_s, coords = c("X_lb93", "Y_lb93"), crs = 2154, agr = "constant", remove = FALSE)
#conversion of Lambert93 coordinates into pseudo mercator (WGS84, EPSg 3857) for kepler.gl
df_s_wgs84 <- st_transform(df_s_lb93, 4326)
#extracting X and Y coordinates from geometry
df_s_xy_wgs84 <- st_coordinates(df_s_wgs84)
#replacing longitude and latitude by X and Y respectively
df_s$X_wgs84 <- df_s_xy_wgs84[,1]
df_s$Y_wgs84 <- df_s_xy_wgs84[,2]
Reorder dataframe
s.df <- df_s[,c("survey_id","row_id","timestamp","date","time","tc","X_lb93","Y_lb93","X_wgs84","Y_wgs84",
"row_total","gender_male","gender_female","age_mean","age_0_7", "age_8_17","age_18_34","age_35_50","age_51_64","age_65",
"posture","engagement","clothing","exposure","activity","mode","stay_time")]
m.df <- df_m[,c("survey_id","row_id","timestamp","date","time","tc",
"row_total","gender_male","gender_female","age_mean", "age_0_7", "age_8_17","age_18_34","age_35_50","age_51_64","age_65",
"engagement","clothing","exposure","mouvement","mode")]
Spatial aggregation
mesh
grid =
st_make_grid(
boundary,
cellsize = 7,
square = FALSE) %>%
st_sf() %>%
st_cast %>%
mutate(
id = 1:n())
grid = grid %>%
mutate(
int = st_intersects(grid,boundary, sparse = F)
) %>%
filter(int == T) %>%
dplyr::select(-int)
plot(grid)

aggregation
hexbin_s =
st_join(
grid,
df_s %>% filter(row_total != 0),
left = FALSE,
join = st_intersects) %>%
group_by(id,fileid) %>%
summarise(
n = n(),
nbp = sum(row_total),
gender_male = sum(gender_male),
gender_female = sum(gender_female))
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
hexbin_m =
st_join(
grid,
df_m %>% filter(row_total != 0),
left = FALSE,
join = st_intersects) %>%
group_by(id,fileid) %>%
summarise(
n = n(),
nbp = sum(row_total),
gender_male = sum(gender_male),
gender_female = sum(gender_female))
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
Plot
theme_carto <-
theme_bw() +
theme(
#axis.line=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.ticks=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(),
#legend.position="none",
panel.background=element_blank(),
#panel.border=element_blank(),
panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),
plot.background=element_blank()
)
bck =
ggplot() +
geom_raster(
data = basemap_df, aes(x = x, y =y), fill = rgb(r = basemap_df$red, g = basemap_df$green, b = basemap_df$blue, maxColorValue = 255),
show.legend = FALSE)+
geom_raster(
data = map_df, aes(x = x, y =y), fill = rgb(r = map_df$red, g = map_df$green, b = map_df$blue, maxColorValue = 255),
show.legend = FALSE)
bck +
#ggplot()+
geom_sf(data=buildings, color = gray(0.5),size = 0.4)+
geom_sf(data=df_s, alpha = 0.2, color = "red")+
geom_sf(data=df_m, alpha = 0.2, color = "blue")+
geom_sf(data=zones, alpha = 1, color = "red",fill = NA, lty = 2, lwd = 5)+
xlim(bbox[["xmin"]],bbox[["xmax"]])+
ylim(bbox[["ymin"]],bbox[["ymax"]])+
theme_carto
ggsave(here("outcomes","all.jpg"))
Saving 7.16 x 4.42 in image

bck +
#ggplot()+
geom_sf(data=grid, color = gray(0.5),size = 0.1, fill = NA)+
geom_sf(data=buildings, color = gray(0.5),size = 0.4)+
geom_sf(data=hexbin_s, aes(fill = nbp,alpha = nbp))+
#geom_sf(data=df_m, alpha = 0.2, color = "blue")+
xlim(bbox[["xmin"]],bbox[["xmax"]])+
ylim(bbox[["ymin"]],bbox[["ymax"]])+
theme_carto
ggsave(here("outcomes","hex_staying.jpg"))
Saving 7.16 x 4.42 in image

bck +
#ggplot()+
geom_sf(data=grid, color = gray(0.5),size = 0.1, fill = NA)+
geom_sf(data=buildings, color = gray(0.5),size = 0.4)+
geom_sf(data=hexbin_m, aes(fill = nbp, alpha = nbp))+
#geom_sf(data=df_m, alpha = 0.2, color = "blue")+
xlim(bbox[["xmin"]],bbox[["xmax"]])+
ylim(bbox[["ymin"]],bbox[["ymax"]])+
theme_carto
ggsave(here("outcomes","hex_moving.jpg"))
Saving 7.16 x 4.42 in image

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBMaWJyYXJpZXMKYGBge3J9CgpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkocHJpc21hdGljKQpsaWJyYXJ5KGFydWxlc0NCQSkKbGlicmFyeSh0aWJibGUpCgpgYGAKCgojIEltcG9ydCBkYXRhCgojIyBvYnNlcnZhdGlvbnMKYGBge3J9CgpmaWxlbmFtZXMgPC0gbGlzdC5maWxlcyhoZXJlKCJzb3VyY2UiKSxwYXR0ZXJuPSIqLmdwa2ckIikKCmxheWVyc19zID0gYygiMDloMzBfc3RheWluZyIsIjEyaDMwX3N0YXlpbmciLCIxNWgzMF9zdGF5aW5nIiwiMThoMzBfc3RheWluZyIpCmxheWVyc19tID0gYygiMDloMzBfbW92aW5nIiwiMTJoMzBfbW92aW5nIiwiMTVoMzBfbW92aW5nIiwiMThoMzBfbW92aW5nIikKCmxpc3RfbSA9IGxpc3QoKQpsaXN0X3MgPSBsaXN0KCkKCmZvciAoaSBpbiBmaWxlbmFtZXMpIHsKCmZpbGVuYW1lID0gaSAgCiAgCmZvciAoaiBpbiBsYXllcnNfcykgewpkZiA9IHN0X3JlYWQoaGVyZSgic291cmNlIixmaWxlbmFtZSksaikKZGYkZmlsZWlkID0gZmlsZW5hbWUKZGYkbGF5ZXIgPSBqCmRmID0gZGYgJT4lIGRwbHlyOjpzZWxlY3QoLVBob3RvLC1tb2RlLC1yb3csLWlkKQpsaXN0X3NbW2xlbmd0aChsaXN0X3MpKzFdXT1kZgpybShkZikKfQoKZm9yIChqIGluIGxheWVyc19tKSB7CmRmID0gc3RfcmVhZChoZXJlKCJzb3VyY2UiLGZpbGVuYW1lKSxqKQpkZiRmaWxlaWQgPSBwYXN0ZTAoZmlsZW5hbWUsaikKZGYkZmlsZWlkID0gZmlsZW5hbWUKZGYkbGF5ZXIgPSBqCmRmID0gZGYgJT4lIGRwbHlyOjpzZWxlY3QoLURpcmVjdGlvbiwtUGhvdG8pCmxpc3RfbVtbbGVuZ3RoKGxpc3RfbSkrMV1dPWRmCnJtKGRmKQp9CgpybShmaWxlbmFtZSkKCn0KCmRmX3MgPSByYmluZGxpc3QobGlzdF9zLHVzZS5uYW1lcyA9IEZBTFNFKSAlPiUgc3RfYXNfc2YoKQpkZl9zICU+JSBnZ3Bsb3QoKSArIGdlb21fc2YoKQpkZl9tID0gcmJpbmRsaXN0KGxpc3RfbSx1c2UubmFtZXMgPSBGQUxTRSkgJT4lIHN0X2FzX3NmKCkKZGZfbSAlPiUgZ2dwbG90KCkgKyBnZW9tX3NmKCkKCmBgYAoKIyMgY29udGV4dApgYGB7cn0KCmJ1aWxkaW5ncyA8LSByZWFkX3NmKGhlcmUoInNvdXJjZSIsImdlb20iLCJjb250ZXh0Lmdwa2ciKSwiYnVpbGRpbmdzIikKcGxvdChidWlsZGluZ3MpCmJvdW5kYXJ5ID0gcmVhZF9zZihoZXJlKCJzb3VyY2UiLCJnZW9tIiwiY29udGV4dC5ncGtnIiksInBlcmltZXRyZSIpICU+JSBzbGljZSgxKQpwbG90KGJvdW5kYXJ5KQp6b25lcyA9IHJlYWRfc2YoaGVyZSgic291cmNlIiwiZ2VvbSIsImNvbnRleHQuZ3BrZyIpLCJ6b25lcyIpCnBsb3Qoem9uZXMpCnRyYWNrID0gcmVhZF9zZihoZXJlKCJzb3VyY2UiLCJnZW9tIiwidHJhY2suZ3BrZyIpLCJ0cmFjazMiKQpwbG90KHRyYWNrKQoKYmFzZW1hcCA9IHN0YWNrKGhlcmUoInNvdXJjZSIsImdlb20iLCJiYXNlbWFwLnRpZiIpKQpiYXNlbWFwX2RmID0gYXMuZGF0YS5mcmFtZShiYXNlbWFwLCB4eT0gVFJVRSkKYmFzZW1hcF9kZiA9IAogIGJhc2VtYXBfZGYgJT4lIAogIHJlbmFtZShyZWQgPSBiYXNlbWFwXzEsICNSZW5hbWUgYmFuZHMKICAgICAgICAgZ3JlZW4gPSBiYXNlbWFwXzIsCiAgICAgICAgIGJsdWUgPSBiYXNlbWFwXzMpICU+JQogIGZpbHRlcihyZWQgIT0gMCkgI2Ryb3AgZGF0YSB3L28gcmdiIGluZm9ybWF0aW9uCgptYXAgPSBzdGFjayhoZXJlKCJzb3VyY2UiLCJnZW9tIiwibWFwX2dlb3JlZmVyZW5jZWRfY2xpcC50aWYiKSkKbWFwX2RmID0gYXMuZGF0YS5mcmFtZShtYXAsIHh5PSBUUlVFKQptYXBfZGYgPSAKICBtYXBfZGYgJT4lIAogIHJlbmFtZShyZWQgPSBtYXBfZ2VvcmVmZXJlbmNlZF9jbGlwXzEsICNSZW5hbWUgYmFuZHMKICAgICAgICAgZ3JlZW4gPSBtYXBfZ2VvcmVmZXJlbmNlZF9jbGlwXzIsCiAgICAgICAgIGJsdWUgPSBtYXBfZ2VvcmVmZXJlbmNlZF9jbGlwXzMpICU+JQogIGZpbHRlcihyZWQgIT0gMCkgI2Ryb3AgZGF0YSB3L28gcmdiIGluZm9ybWF0aW9uCgpiYm94IDwtIHN0X2Jib3goc3RfYnVmZmVyKGJvdW5kYXJ5LGRpc3QgPSA1LCBqb2luU3R5bGU9IlJPVU5EIikpICNnbG9iYWwKCmBgYAoKI0RhdGEgb3JnYW5pc2F0aW9uCgojIyBJRHMKYGBge3J9Cgojc3VydmV5X2lkCmRmX3Mkc3VydmV5X2lkIDwtIHBhc3RlMChzdWJzdHIoZGZfcyRwYXRoLHN0YXJ0PTc2LHN0b3A9ODEpLCJfIixzdWJzdHIoZGZfcyRwYXRoLHN0YXJ0PTgzLHN0b3A9ODcpKQpkZl9zJHN1cnZleV9pZDwtZ3N1YigiLSIsIiIsZGZfcyRzdXJ2ZXlfaWQpCmRmX3Mkc3VydmV5X2lkPC1nc3ViKCJfIiwiIixkZl9zJHN1cnZleV9pZCkKCmRmX20kc3VydmV5X2lkIDwtIHBhc3RlMChzdWJzdHIoZGZfbSRwYXRoLHN0YXJ0PTc2LHN0b3A9ODEpLCJfIixzdWJzdHIoZGZfbSRwYXRoLHN0YXJ0PTgzLHN0b3A9ODcpKQpkZl9tJHN1cnZleV9pZDwtZ3N1YigiLSIsIiIsZGZfbSRzdXJ2ZXlfaWQpCmRmX20kc3VydmV5X2lkPC1nc3ViKCJfIiwiIixkZl9tJHN1cnZleV9pZCkKCiMgcm93X2lkCmRmX3Mkcm93X2lkIDwtIHBhc3RlKGRmX3Mkc3VydmV5X2lkLCBhdmUoZGZfcyRpZCxkZl9zJHN1cnZleV9pZCwgRlVOID0gc2VxX2Fsb25nKSwgc2VwPSIiKQpkZl9tJHJvd19pZCA8LSBwYXN0ZShkZl9tJHN1cnZleV9pZCwgYXZlKGRmX20kaWQsZGZfbSRzdXJ2ZXlfaWQsIEZVTiA9IHNlcV9hbG9uZyksIHNlcD0iIikKCiN0YwpkZl9zJHRjIDwtIHN1YnN0cihkZl9zJHBhdGgsc3RhcnQ9ODMsc3RvcD04NykKZGZfcyR0YzwtZ3N1YigiLSIsIjoiLGRmX3MkdGMpCmRmX20kdGMgPC0gc3Vic3RyKGRmX20kcGF0aCxzdGFydD04MyxzdG9wPTg3KQpkZl9tJHRjPC1nc3ViKCItIiwiOiIsZGZfbSR0YykKCmBgYAoKIyMgTWVhbnMgJiB0b3RhbHMKYGBge3J9CgojIFJvd190b3RhbApkZl9zJHJvd190b3RhbCA8LSBkZl9zJGdlbmRlcl9tYWxlK2RmX3MkZ2VuZGVyX2ZlbWFsZQpkZl9tJHJvd190b3RhbCA8LSBkZl9tJGdlbmRlcl9tYWxlK2RmX20kZ2VuZGVyX2ZlbWFsZQoKIyBNZWFuIGFnZSBwZXIgZ3JvdXAKZGZfcyRhZ2VfbWVhbiA8LSByb3VuZCgoKGRmX3MkYWdlXzAuMTQqNykrKGRmX3MkYWdlXzE1LjI0KjE5LjUpKyhkZl9zJGFnZV8yNS40NCozNC41KSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGZfcyRhZ2VfNDUuNjQqNTQuNSkrKGRmX3MkYWdlXzY1Ljc0KjY5LjUpKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkZl9zJGFnZV83NXAqODApKS9kZl9zJHJvd190b3RhbCxkaWdpdHMgPSAxKQoKZGZfbSRhZ2VfbWVhbiA8LSByb3VuZCgoKGRmX20kYWdlXzAuMTQqNykrKGRmX20kYWdlXzE1LjI0KjE5LjUpKyhkZl9tJGFnZV8yNS40NCozNC41KSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGZfbSRhZ2VfNDUuNjQqNTQuNSkrKGRmX20kYWdlXzY1Ljc0KjY5LjUpKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkZl9tJGFnZV83NXAqODApKS9kZl9tJHJvd190b3RhbCxkaWdpdHMgPSAxKQoKYGBgCgoKIyMgU2VwYXJhdGluZyBjb2x1bW5zIG9mIHRpbWUgJiBkYXRlIGZyb20gdGltZXN0YW1wCmBgYHtyfQpkZl9zJHRpbWVzdGFtcCA8LSBnc3ViKCdUJywnICcsZGZfcyR0aW1lc3RhbXApCmRmX3MkdGltZXN0YW1wIDwtIHN1YnN0cihkZl9zJHRpbWVzdGFtcCxzdGFydD0xLHN0b3A9MTkpCmRmX3MkZGF0ZSA8LSBmb3JtYXQoYXMuUE9TSVhjdChzdHJwdGltZShkZl9zJHRpbWVzdGFtcCwiJVktJW0tJWQiLHR6PSIiKSksZm9ybWF0ID0gIiVZLSVtLSVkIikgIyBzZXBhcmF0ZSBkYXRlIGNvbHVtbgpkZl9zJHRpbWUgPC0gZm9ybWF0KGFzLlBPU0lYY3Qoc3RycHRpbWUoZGZfcyR0aW1lc3RhbXAsIiVZLSVtLSVkICVIOiVNOiVTIix0ej0iIikpICxmb3JtYXQgPSAiJUg6JU06JVMiKSAjIHNlcGFyYXRlIHRpbWUgY29sdW1uCgpkZl9tJHRpbWVzdGFtcCA8LSBnc3ViKCdUJywnICcsZGZfbSR0aW1lc3RhbXApCmRmX20kdGltZXN0YW1wIDwtIHN1YnN0cihkZl9tJHRpbWVzdGFtcCxzdGFydD0xLHN0b3A9MTkpCmRmX20kZGF0ZSA8LSBmb3JtYXQoYXMuUE9TSVhjdChzdHJwdGltZShkZl9tJHRpbWVzdGFtcCwiJVktJW0tJWQiLHR6PSIiKSksZm9ybWF0ID0gIiVZLSVtLSVkIikgIyBzZXBhcmF0ZSBkYXRlIGNvbHVtbgpkZl9tJHRpbWUgPC0gZm9ybWF0KGFzLlBPU0lYY3Qoc3RycHRpbWUoZGZfbSR0aW1lc3RhbXAsIiVZLSVtLSVkICVIOiVNOiVTIix0ej0iIikpICxmb3JtYXQgPSAiJUg6JU06JVMiKSAjIHNlcGFyYXRlIHRpbWUgY29sdW1uCmBgYAoKCiMjIEFkZGluZyBjb29yZGluYXRlcyBXR1M4NApgYGB7cn0KbGlicmFyeShzZikKCiNjb252ZXJzaW9uIG9mIHBvaW50cyBpbnRvIHNwYXRpYWwgZmVhdHVyZSBvYmplY3QgCmRmX3NfbGI5MyA8LSBzdF9hc19zZihkZl9zLCBjb29yZHMgPSBjKCJYX2xiOTMiLCAiWV9sYjkzIiksIGNycyA9IDIxNTQsIGFnciA9ICJjb25zdGFudCIsIHJlbW92ZSA9IEZBTFNFKQogIAojY29udmVyc2lvbiBvZiBMYW1iZXJ0OTMgY29vcmRpbmF0ZXMgaW50byBwc2V1ZG8gbWVyY2F0b3IgKFdHUzg0LCBFUFNnIDM4NTcpIGZvciBrZXBsZXIuZ2wKZGZfc193Z3M4NCA8LSBzdF90cmFuc2Zvcm0oZGZfc19sYjkzLCA0MzI2KQogIAojZXh0cmFjdGluZyBYIGFuZCBZIGNvb3JkaW5hdGVzIGZyb20gZ2VvbWV0cnkKZGZfc194eV93Z3M4NCA8LSBzdF9jb29yZGluYXRlcyhkZl9zX3dnczg0KQogIAojcmVwbGFjaW5nIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgYnkgWCBhbmQgWSByZXNwZWN0aXZlbHkKZGZfcyRYX3dnczg0IDwtIGRmX3NfeHlfd2dzODRbLDFdCmRmX3MkWV93Z3M4NCA8LSBkZl9zX3h5X3dnczg0WywyXQoKYGBgCgojIyBSZW9yZGVyIGRhdGFmcmFtZQpgYGB7cn0Kcy5kZiA8LSBkZl9zWyxjKCJzdXJ2ZXlfaWQiLCJyb3dfaWQiLCJ0aW1lc3RhbXAiLCJkYXRlIiwidGltZSIsInRjIiwiWF9sYjkzIiwiWV9sYjkzIiwiWF93Z3M4NCIsIllfd2dzODQiLAogICAgICAgICAgICAgICAgICAgICAgInJvd190b3RhbCIsImdlbmRlcl9tYWxlIiwiZ2VuZGVyX2ZlbWFsZSIsImFnZV9tZWFuIiwiYWdlXzBfNyIsICJhZ2VfOF8xNyIsImFnZV8xOF8zNCIsImFnZV8zNV81MCIsImFnZV81MV82NCIsImFnZV82NSIsCiAgICAgICAgICAgICAgICAgICAgICAicG9zdHVyZSIsImVuZ2FnZW1lbnQiLCJjbG90aGluZyIsImV4cG9zdXJlIiwiYWN0aXZpdHkiLCJtb2RlIiwic3RheV90aW1lIildCgptLmRmIDwtIGRmX21bLGMoInN1cnZleV9pZCIsInJvd19pZCIsInRpbWVzdGFtcCIsImRhdGUiLCJ0aW1lIiwidGMiLAogICAgICAgICAgICAgICAgICAgICAgInJvd190b3RhbCIsImdlbmRlcl9tYWxlIiwiZ2VuZGVyX2ZlbWFsZSIsImFnZV9tZWFuIiwgImFnZV8wXzciLCAiYWdlXzhfMTciLCJhZ2VfMThfMzQiLCJhZ2VfMzVfNTAiLCJhZ2VfNTFfNjQiLCJhZ2VfNjUiLAogICAgICAgICAgICAgICAgICAgICAgImVuZ2FnZW1lbnQiLCJjbG90aGluZyIsImV4cG9zdXJlIiwibW91dmVtZW50IiwibW9kZSIpXQpgYGAKCgojIFNwYXRpYWwgYWdncmVnYXRpb24KCiMjIG1lc2gKYGBge3J9CgpncmlkID0gCiAgc3RfbWFrZV9ncmlkKAogICAgYm91bmRhcnksCiAgICBjZWxsc2l6ZSA9IDcsCiAgICBzcXVhcmUgPSBGQUxTRSkgJT4lIAogIHN0X3NmKCkgJT4lIAogIHN0X2Nhc3QgJT4lCiAgbXV0YXRlKAogICAgaWQgPSAxOm4oKSkKCmdyaWQgPSBncmlkICU+JQogIG11dGF0ZSgKICAgIGludCA9IHN0X2ludGVyc2VjdHMoZ3JpZCxib3VuZGFyeSwgc3BhcnNlID0gRikKICAgICkgJT4lCiAgZmlsdGVyKGludCA9PSBUKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1pbnQpCiAgCnBsb3QoZ3JpZCkKCmBgYAoKCiMjIGFnZ3JlZ2F0aW9uCmBgYHtyfQpoZXhiaW5fcyA9CiAgc3Rfam9pbigKICAgIGdyaWQsCiAgICBkZl9zICU+JSBmaWx0ZXIocm93X3RvdGFsICE9IDApLAogICAgbGVmdCA9IEZBTFNFLAogICAgam9pbiA9IHN0X2ludGVyc2VjdHMpICU+JQogIGdyb3VwX2J5KGlkLGZpbGVpZCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIG5icCA9IHN1bShyb3dfdG90YWwpLAogICAgZ2VuZGVyX21hbGUgPSBzdW0oZ2VuZGVyX21hbGUpLAogICAgZ2VuZGVyX2ZlbWFsZSA9IHN1bShnZW5kZXJfZmVtYWxlKSkKCmhleGJpbl9tID0KICBzdF9qb2luKAogICAgZ3JpZCwKICAgIGRmX20gJT4lIGZpbHRlcihyb3dfdG90YWwgIT0gMCksCiAgICBsZWZ0ID0gRkFMU0UsCiAgICBqb2luID0gc3RfaW50ZXJzZWN0cykgJT4lCiAgZ3JvdXBfYnkoaWQsZmlsZWlkKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgbmJwID0gc3VtKHJvd190b3RhbCksCiAgICBnZW5kZXJfbWFsZSA9IHN1bShnZW5kZXJfbWFsZSksCiAgICBnZW5kZXJfZmVtYWxlID0gc3VtKGdlbmRlcl9mZW1hbGUpKQoKYGBgCgoKIyBQbG90CgpgYGB7cn0KCnRoZW1lX2NhcnRvIDwtCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICAjYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3M9ZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksCiAgICAjbGVnZW5kLnBvc2l0aW9uPSJub25lIiwKICAgIHBhbmVsLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLAogICAgI3BhbmVsLmJvcmRlcj1lbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3I9ZWxlbWVudF9ibGFuaygpLAogICAgcGxvdC5iYWNrZ3JvdW5kPWVsZW1lbnRfYmxhbmsoKQogICAgKQoKYGBgCgoKYGBge3J9CgpiY2sgPQogIGdncGxvdCgpICsKICBnZW9tX3Jhc3RlcigKICAgIGRhdGEgPSBiYXNlbWFwX2RmLCBhZXMoeCA9IHgsIHkgPXkpLCBmaWxsID0gcmdiKHIgPSBiYXNlbWFwX2RmJHJlZCwgZyA9IGJhc2VtYXBfZGYkZ3JlZW4sIGIgPSBiYXNlbWFwX2RmJGJsdWUsIG1heENvbG9yVmFsdWUgPSAyNTUpLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkrCiAgZ2VvbV9yYXN0ZXIoCiAgICBkYXRhID0gbWFwX2RmLCBhZXMoeCA9IHgsIHkgPXkpLCBmaWxsID0gcmdiKHIgPSBtYXBfZGYkcmVkLCBnID0gbWFwX2RmJGdyZWVuLCBiID0gbWFwX2RmJGJsdWUsIG1heENvbG9yVmFsdWUgPSAyNTUpLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkKCmJjayArCiNnZ3Bsb3QoKSsKICBnZW9tX3NmKGRhdGE9YnVpbGRpbmdzLCBjb2xvciA9IGdyYXkoMC41KSxzaXplID0gMC40KSsKICBnZW9tX3NmKGRhdGE9ZGZfcywgYWxwaGEgPSAwLjIsIGNvbG9yID0gInJlZCIpKwogIGdlb21fc2YoZGF0YT1kZl9tLCBhbHBoYSA9IDAuMiwgY29sb3IgPSAiYmx1ZSIpKwogIGdlb21fc2YoZGF0YT16b25lcywgYWxwaGEgPSAxLCBjb2xvciA9ICJyZWQiLGZpbGwgPSBOQSwgbHR5ID0gMiwgbHdkID0gNSkrCiAgeGxpbShiYm94W1sieG1pbiJdXSxiYm94W1sieG1heCJdXSkrCiAgeWxpbShiYm94W1sieW1pbiJdXSxiYm94W1sieW1heCJdXSkrCiAgdGhlbWVfY2FydG8KCmdnc2F2ZShoZXJlKCJvdXRjb21lcyIsImFsbC5qcGciKSkKCmJjayArCiNnZ3Bsb3QoKSsgIAogIGdlb21fc2YoZGF0YT1ncmlkLCBjb2xvciA9IGdyYXkoMC41KSxzaXplID0gMC4xLCBmaWxsID0gTkEpKwogIGdlb21fc2YoZGF0YT1idWlsZGluZ3MsIGNvbG9yID0gZ3JheSgwLjUpLHNpemUgPSAwLjQpKwogIGdlb21fc2YoZGF0YT1oZXhiaW5fcywgYWVzKGZpbGwgPSBuYnAsYWxwaGEgPSBuYnApKSsKICAjZ2VvbV9zZihkYXRhPWRmX20sIGFscGhhID0gMC4yLCBjb2xvciA9ICJibHVlIikrCiAgeGxpbShiYm94W1sieG1pbiJdXSxiYm94W1sieG1heCJdXSkrCiAgeWxpbShiYm94W1sieW1pbiJdXSxiYm94W1sieW1heCJdXSkrCiAgdGhlbWVfY2FydG8KCmdnc2F2ZShoZXJlKCJvdXRjb21lcyIsImhleF9zdGF5aW5nLmpwZyIpKQoKYmNrICsKI2dncGxvdCgpKyAgCiAgZ2VvbV9zZihkYXRhPWdyaWQsIGNvbG9yID0gZ3JheSgwLjUpLHNpemUgPSAwLjEsIGZpbGwgPSBOQSkrCiAgZ2VvbV9zZihkYXRhPWJ1aWxkaW5ncywgY29sb3IgPSBncmF5KDAuNSksc2l6ZSA9IDAuNCkrCiAgZ2VvbV9zZihkYXRhPWhleGJpbl9tLCBhZXMoZmlsbCA9IG5icCwgYWxwaGEgPSBuYnApKSsKICAjZ2VvbV9zZihkYXRhPWRmX20sIGFscGhhID0gMC4yLCBjb2xvciA9ICJibHVlIikrCiAgeGxpbShiYm94W1sieG1pbiJdXSxiYm94W1sieG1heCJdXSkrCiAgeWxpbShiYm94W1sieW1pbiJdXSxiYm94W1sieW1heCJdXSkrCiAgdGhlbWVfY2FydG8KCmdnc2F2ZShoZXJlKCJvdXRjb21lcyIsImhleF9tb3ZpbmcuanBnIikpCgpgYGAKCg==